package hamsterpolice.todo;

import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import hamsterpolice.todo.data.DataNotFoundException;
import hamsterpolice.todo.data.DatabaseConstraintException;
import hamsterpolice.todo.model.Category;
import hamsterpolice.todo.model.Location;
import hamsterpolice.todo.model.ToDoItem;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.location.Address;
import android.location.Geocoder;
import android.os.Bundle;
import android.text.format.Time;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TextView;

public class EditToDoItemActivity extends Activity implements Editing,
		android.content.DialogInterface.OnClickListener {

	private static final String TAG = "EditTodoListActivity";

	private static final DateFormat dateFormat = SimpleDateFormat
			.getDateInstance(DateFormat.SHORT);
	private ToDoItem edit = null;
	private EditText mChangeItemName = null;
	private EditText mEditItemDescription = null;
	private EditText mEditLocation = null;
	private TextView mDueDate = null;
	private CheckBox mItemCompletedCheckBox = null;
	private Category currentCategory = null;

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.edit_item);

		mChangeItemName = (EditText) findViewById(R.id.name);
		mEditItemDescription = (EditText) findViewById(R.id.description);
		mEditLocation = (EditText) findViewById(R.id.location);
		mDueDate = (TextView) findViewById(R.id.dueDate);
		mItemCompletedCheckBox = (CheckBox) findViewById(R.id.completed);

		// Get User and Todo Item passed into Activity from Database
		Bundle extras = getIntent().getExtras();
		long todoItemID = extras.getLong(KEY_TODO_ITEM_ID, -1L);

		if (todoItemID == -1L) {
			Log.e(TAG, "Edit Activity was opened but no " + KEY_TODO_ITEM_ID
					+ " value was provided in Intent extras!");
			// Just close the activity if it was opened with no item ID?
			// there's nothing we can do in this case
			finish();
		} else {
			load(todoItemID);
		}
	}

	private void load(long id) {
		try {
			edit = ToDoItem.get(this, id);
		} catch (DataNotFoundException e) {
			Log.e(TAG, String.format("Error getting todo item %s", id), e);
		}

		mChangeItemName.setText(edit.getName());
		mEditItemDescription.setText(edit.getDescription());
		if (edit.getLocation() != null)
			mEditLocation.setText(edit.getLocation().getDescription());
		mItemCompletedCheckBox.setChecked(edit.isCompleted());
		initializeChangeCategorySpinner();

		if (edit.getDueDate() != null) {
			mDueDate.setText(dateFormat.format(new Date(edit.getDueDate()
					.toMillis(false))));
		} else {
			mDueDate.setText("none");
		}

		// Listener to change Due Date when label is clicked
		mDueDate.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				final Dialog dueDialog = new Dialog(EditToDoItemActivity.this);
				dueDialog.setContentView(R.layout.date_select);
				dueDialog.setTitle("Due Date");
				dueDialog.setCancelable(true);

				final DatePicker dueBefore = (DatePicker) dueDialog
						.findViewById(R.id.datePicker);

				Time time = edit.getDueDate();
				if (time != null)
					dueBefore.init(time.year, time.month, time.monthDay, null);

				Button b = (Button) dueDialog.findViewById(R.id.clearButton);
				b.setOnClickListener(new OnClickListener() {
					@Override
					public void onClick(View v) {
						edit.setDueDate(null);
						mDueDate.setText("none");
						dueDialog.dismiss();
					}
				});

				b = (Button) dueDialog.findViewById(R.id.saveButton);
				b.setOnClickListener(new OnClickListener() {
					@Override
					public void onClick(View v) {
						Time time = new Time();
						time.set(dueBefore.getDayOfMonth(),
								dueBefore.getMonth(), dueBefore.getYear());
						edit.setDueDate(time);
						mDueDate.setText(dateFormat.format(new Date(time
								.toMillis(false))));
						dueDialog.dismiss();
					}
				});

				dueDialog.show();
			}
		});
	}

	private void initializeChangeCategorySpinner() {
		ArrayList<Category> categoryList = (ArrayList<Category>) Category
				.getAll(this, edit.getUser());

		Category none = new Category(this);
		none.setName("No Category");
		categoryList.add(0, none);

		ArrayAdapter<Category> mAdapter = new ArrayAdapter<Category>(this,
				android.R.layout.simple_spinner_item, categoryList);

		Spinner s = (Spinner) findViewById(R.id.category);

		s.setAdapter(mAdapter);

		s.setPromptId(R.string.chooseCategory);

		int selection = 0;
		if (edit.getCategory() != null) {
			for (int i = 0; i < categoryList.size(); i++) {
				if (categoryList.get(i).getName()
						.equals(edit.getCategory().getName())) {
					selection = i;
				}
			}
		}

		s.setSelection(selection);

		s.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {

			@Override
			public void onItemSelected(AdapterView<?> adapter, View v, int i,
					long lng) {

				if (i == 0)
					currentCategory = null;
				else
					currentCategory = (Category) adapter.getItemAtPosition(i);
			}

			@Override
			public void onNothingSelected(AdapterView<?> arg0) {
				return;
			}
		});
	}

	private void save() throws DatabaseConstraintException {
		edit.setName(mChangeItemName.getText().toString());
		edit.setDescription(mEditItemDescription.getText().toString());
		edit.setCompleted(mItemCompletedCheckBox.isChecked());
		edit.setCategory(currentCategory);

		// Set Location with Geocoding
		String locationDesc = mEditLocation.getText().toString();
		if (locationDesc.trim().length() == 0) {
			edit.setLocation(null);
		} else if (edit.getLocation() == null
				|| !edit.getLocation().getDescription().equals(locationDesc)) {
			// Location has changed

			Geocoder geocoder = new Geocoder(this);
			try {
				List<Address> addresses = geocoder.getFromLocationName(
						locationDesc, 1);
				if (addresses.size() > 0) {
					Address address = addresses.get(0);

					if (address.getAddressLine(0) != null){
						int i = 0;
						String line;
						locationDesc = "";
						while((line = address.getAddressLine(i++)) != null){
							if(locationDesc.length() > 0)
								locationDesc += ", ";
							locationDesc += line;
						}
					}

					Location location = new Location(locationDesc,
							address.getLatitude(), address.getLongitude());
					edit.setLocation(location);
				}
			} catch (IOException e) {
				Log.e(TAG, String.format("Error getting geocoding for %s",
						locationDesc), e);
			}
		}

		edit.save();
	}

	public void onBackPressed() {
		try {
			save();
			finish();
		} catch (DatabaseConstraintException e) {
			Log.e(TAG, "Constraint exception when saving ToDoItem", e);
			throw new RuntimeException(e);
		}
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		super.onCreateOptionsMenu(menu);
		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.edit, menu);
		return true;
	}

	@Override
	public void onClick(DialogInterface dialog, int which) {
		switch (which) {
		case DialogInterface.BUTTON_POSITIVE:
			edit.delete();
			finish();
			break;

		case DialogInterface.BUTTON_NEGATIVE:
			break;
		}
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		super.onOptionsItemSelected(item);

		switch (item.getItemId()) {
		case R.id.discard:
			finish();
			return true;
		case R.id.save:
			try {
				save();
				finish();
			} catch (DatabaseConstraintException e) {
				Log.e(TAG, "Constraint exception when saving ToDoItem", e);
				throw new RuntimeException(e);
			}
			return true;
		case R.id.delete:
			AlertDialog.Builder builder = new AlertDialog.Builder(this);
			builder.setMessage("Are you sure you want to delete this item?")
					.setPositiveButton("Yes", this)
					.setNegativeButton("No", this).show();
			return true;
		}

		return false;
	}

}
